
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>持久化与消息可靠性 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>持久化与消息可靠性 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">RabbitMQ中的交换机（Exchange）主要负责什么？请列举文档中提到的四种常见交换机类型及其路由规则。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">交换机负责将消息从生产者路由到不同的队列。四种常见的交换机类型及其规则是：1. Direct Exchange：基于路由键精确匹配消息；2. Fanout Exchange：将消息广播到所有绑定的队列；3. Topic Exchange：通过主题模式（通配符）路由消息；4. Headers Exchange：通过消息头进行路由。</div>
          </div>
          <div class="card-source">来源: 文档中「1.2 RabbitMQ 的工作原理」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">为了确保消息在RabbitMQ服务器崩溃或重启后不丢失，需要对哪些部分进行持久化设置？请分别说明如何配置。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">需要同时对队列和消息进行持久化设置。1. 队列持久化：在声明队列时将durable参数设为true，例如`channel.queueDeclare("queueName", true, ...)`。2. 消息持久化：在发送消息时，通过设置`deliveryMode`为2来实现，例如`new AMQP.BasicProperties.Builder().deliveryMode(2).build()`。</div>
          </div>
          <div class="card-source">来源: 文档中「2 队列持久化」和「3 消息持久化」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">启用消息持久化虽然能保证数据安全，但会带来哪些性能开销？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">启用消息持久化会引入三个主要的性能开销：1. 磁盘IO：将消息写入磁盘的速度比内存慢，会降低吞吐量。2. 内存占用：需要更多的内存和磁盘空间来存储消息。3. 同步写入：每次持久化操作需要等待磁盘确认，可能导致延迟增加。</div>
          </div>
          <div class="card-source">来源: 文档中「4 消息持久化与性能的权衡」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">RabbitMQ提供了哪两种核心的消息确认机制来保证消息的可靠性？它们分别作用于哪个环节？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">RabbitMQ提供了两种核心确认机制：1. 生产者确认（Publisher Confirms）：作用于生产者到RabbitMQ服务器的环节，确保消息已成功被RabbitMQ接收并存储。2. 消费者确认（Consumer Acknowledgments）：作用于RabbitMQ服务器到消费者的环节，确保消息被消费者成功处理后才从队列中移除。</div>
          </div>
          <div class="card-source">来源: 文档中「2 消息确认与应答机制」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">什么是死信队列（DLQ）？请描述导致消息进入死信队列的三种常见场景。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">死信队列（Dead Letter Queue, DLQ）是用于存放无法被成功处理的消息的专门队列。导致消息进入死信队列的常见场景包括：1. 消费者处理失败并且拒绝了消息（nack）；2. 消息设置了过期时间（TTL），在超时后仍未被消费；3. 队列已满，达到了最大长度限制。</div>
          </div>
          <div class="card-source">来源: 文档中「3 消息重试与死信队列（DLQ）」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">概念</div>
          <div class="card-question">在消息处理中，什么是“幂等性”？文档中提到了哪两种常见方法来保证消息处理的幂等性？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">概念</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">幂等性指的是无论消费者重复处理同一条消息多少次，最终产生的结果都是一致的。保证幂等性的两种常见方法是：1. 唯一标识符：为每条消息附加一个唯一ID，消费者处理前先检查该ID是否已被处理。2. 数据库设计：利用数据库的唯一约束或去重机制，确保重复的消息不会导致数据重复插入。</div>
          </div>
          <div class="card-source">来源: 文档中「4 幂等性与消息重复处理」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">RabbitMQ的镜像队列（Mirrored Queues）是如何实现高可用性的？其工作原理是怎样的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">镜像队列通过将队列的副本（镜像）复制到集群中的其他节点来增强高可用性。其工作原理是：每个镜像队列有一个主队列（Master）和多个镜像队列（Mirror）。主队列负责接收消息，并自动将消息同步到所有镜像队列。当主队列所在的节点故障时，系统会自动将一个镜像队列提升为新的主队列，从而保证消息服务的连续性。</div>
          </div>
          <div class="card-source">来源: 文档中「2 镜像队列（Mirrored Queues）」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">在RabbitMQ集群中，什么是“网络分区”（Split Brain）问题？为了应对此问题，RabbitMQ提供了哪三种处理策略？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">网络分区（Split Brain）问题指的是集群中的节点因网络故障无法正常通信，导致集群分裂成多个部分，每个部分都可能认为自己是主导。RabbitMQ提供的三种处理策略是：1. Autoheal：自动选择一个分区作为主分区，并合并其他分区的消息。2. Ignore：忽略网络分区，继续运行，但可能导致数据不一致。3. Stop：停止处理，直到网络问题解决。</div>
          </div>
          <div class="card-source">来源: 文档中「5 网络分区与容错性」部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">为了防止高并发下队列阻塞导致性能下降，可以通过`basic.qos`设置来优化。这个设置具体是做什么的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer"> `basic.qos`用于设置消费者的预取计数（prefetch count）。它限制了消费者一次性从队列中获取并待处理的消息数量。通过设置一个合理的预取值，可以避免单个消费者一次性占用过多消息而导致处理不过来，从而让消息能更均匀地分发给多个消费者，提高系统的整体吞吐量。</div>
          </div>
          <div class="card-source">来源: 文档中「1.3 减少队列的阻塞」部分</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
